package com.example.calendar.ui.components.calendar

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.calendar.ui.theme.calendarDayDisabled
import com.example.calendar.ui.theme.calendarOtherMonthText
import com.example.calendar.ui.theme.calendarSelectedDayBackground
import com.example.calendar.ui.theme.calendarSelectedDayText
import com.example.calendar.ui.theme.calendarTodayBackground
import com.example.calendar.ui.theme.calendarTodayText
import com.example.calendar.ui.theme.calendarWeekendText
import org.threeten.bp.DayOfWeek
import org.threeten.bp.LocalDate
import org.threeten.bp.YearMonth
import org.threeten.bp.format.TextStyle
import java.util.Locale

/**
 * A composable that displays a month calendar.
 *
 * @param yearMonth The year and month to display
 * @param selectedDate The date that is currently selected
 * @param onDateSelected Callback when a date is selected
 * @param eventDates List of dates that have events
 * @param modifier Modifier for the calendar
 */
@Composable
fun MonthCalendar(
    yearMonth: YearMonth,
    selectedDate: LocalDate,
    onDateSelected: (LocalDate) -> Unit,
    eventDates: List<LocalDate> = emptyList(),
    modifier: Modifier = Modifier
) {
    val today = LocalDate.now()
    val firstDayOfMonth = yearMonth.atDay(1)
    val daysInMonth = yearMonth.lengthOfMonth()
    
    // Find the day of week for the first day of month (0 = Monday, 6 = Sunday with DayOfWeek.getValue())
    val firstDayOfWeekValue = firstDayOfMonth.dayOfWeek.value % 7
    
    // Calculate days from previous and next months to fill the calendar grid
    val daysFromPrevMonth = firstDayOfWeekValue
    val daysFromNextMonth = (42 - daysInMonth - daysFromPrevMonth) % 7
    
    val prevMonth = yearMonth.minusMonths(1)
    val nextMonth = yearMonth.plusMonths(1)
    
    val prevMonthDays = if (daysFromPrevMonth > 0) {
        val prevMonthLength = prevMonth.lengthOfMonth()
        (prevMonthLength - daysFromPrevMonth + 1..prevMonthLength).map { 
            prevMonth.atDay(it) 
        }
    } else {
        emptyList()
    }
    
    val currentMonthDays = (1..daysInMonth).map { 
        yearMonth.atDay(it) 
    }
    
    val nextMonthDays = (1..daysFromNextMonth).map { 
        nextMonth.atDay(it) 
    }
    
    val allDates = prevMonthDays + currentMonthDays + nextMonthDays
    
    // Group dates into weeks
    val weeks = allDates.chunked(7)
    
    Card(
        modifier = modifier.fillMaxWidth(),
        elevation = CardDefaults.cardElevation(defaultElevation = 4.dp),
        border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant)
    ) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(8.dp)
        ) {
            // Day of week headers
            WeekdayHeader()
            
            // Calendar grid
            Column {
                weeks.forEach { week ->
                    WeekRow(
                        week = week,
                        selectedDate = selectedDate,
                        today = today,
                        currentMonth = yearMonth,
                        eventDates = eventDates,
                        onDateSelected = onDateSelected
                    )
                }
            }
        }
    }
}

@Composable
fun WeekdayHeader() {
    Row(
        modifier = Modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.SpaceEvenly
    ) {
        val daysOfWeek = getOrderedDaysOfWeek()
        daysOfWeek.forEach { dayOfWeek ->
            Box(
                modifier = Modifier
                    .weight(1f)
                    .padding(vertical = 4.dp),
                contentAlignment = Alignment.Center
            ) {
                Text(
                    text = dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.getDefault()),
                    style = MaterialTheme.typography.bodySmall,
                    color = if (isWeekend(dayOfWeek)) calendarWeekendText else MaterialTheme.colorScheme.onSurface
                )
            }
        }
    }
}

@Composable
fun WeekRow(
    week: List<LocalDate>,
    selectedDate: LocalDate,
    today: LocalDate,
    currentMonth: YearMonth,
    eventDates: List<LocalDate>,
    onDateSelected: (LocalDate) -> Unit
) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.SpaceEvenly
    ) {
        week.forEach { date ->
            CalendarDay(
                date = date,
                isSelected = date == selectedDate,
                isToday = date == today,
                isCurrentMonth = date.month == currentMonth.month,
                hasEvent = eventDates.contains(date),
                onDateSelected = onDateSelected
            )
        }
    }
}

@Composable
fun CalendarDay(
    date: LocalDate,
    isSelected: Boolean,
    isToday: Boolean,
    isCurrentMonth: Boolean,
    hasEvent: Boolean,
    onDateSelected: (LocalDate) -> Unit
) {
    Box(
        modifier = Modifier
            .weight(1f)
            .aspectRatio(1f)
            .padding(2.dp)
            .clip(CircleShape)
            .background(
                when {
                    isSelected -> calendarSelectedDayBackground
                    isToday -> calendarTodayBackground
                    else -> Color.Transparent
                }
            )
            .clickable { onDateSelected(date) },
        contentAlignment = Alignment.Center
    ) {
        Column(
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center
        ) {
            Text(
                text = date.dayOfMonth.toString(),
                style = MaterialTheme.typography.bodyMedium,
                color = when {
                    isSelected -> calendarSelectedDayText
                    isToday -> calendarTodayText
                    !isCurrentMonth -> calendarOtherMonthText
                    isWeekend(date.dayOfWeek) -> calendarWeekendText
                    else -> MaterialTheme.colorScheme.onSurface
                },
                textAlign = TextAlign.Center
            )
            
            // Event indicator
            if (hasEvent) {
                Box(
                    modifier = Modifier
                        .padding(top = 2.dp)
                        .size(4.dp)
                        .background(
                            color = when {
                                isSelected -> calendarSelectedDayText
                                else -> MaterialTheme.colorScheme.primary
                            },
                            shape = CircleShape
                        )
                )
            }
        }
    }
}

// Get days of week starting with Monday (or customizable to user preference)
fun getOrderedDaysOfWeek(): List<DayOfWeek> {
    return DayOfWeek.values().toList().sortedBy { it.value % 7 }
}

fun isWeekend(dayOfWeek: DayOfWeek): Boolean {
    return dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY
}

@Preview(showBackground = true)
@Composable
fun MonthCalendarPreview() {
    MaterialTheme {
        MonthCalendar(
            yearMonth = YearMonth.now(),
            selectedDate = LocalDate.now(),
            onDateSelected = {},
            eventDates = listOf(
                LocalDate.now(),
                LocalDate.now().plusDays(3),
                LocalDate.now().plusDays(7)
            ),
            modifier = Modifier.padding(16.dp)
        )
    }
} 